package com.module.bp.view;

import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;

import com.dalonedrau.jogl.engine.GameApplet;
import com.dalonedrau.jogl.engine.GlobalConsts;
import com.dalonedrau.jogl.engine.Interface;
import com.dalonedrau.jogl.engine.JOGLErrorHandler;
import com.dalonedrau.jogl.opengl.View;
import com.dalonedrau.jogl.opengl.ui.OverworldMap;
import com.dalonedrau.jogl.opengl.ui.panel.LandscapePagePanel;
import com.dalonedrau.jogl.opengl.ui.panel.Panel;
import com.dalonedrau.vectors.Vector3;
import com.module.bp.engine.Init;
import com.module.bp.player.BPConsts;
import com.module.bp.player.BPParty;
import com.module.bp.ui.PartyStatsBar;
import com.module.bp.ui.PartyViewer;

/**
 * The title screen view.
 * @author Donald
 */
public final class OverworldView implements View {
	/** the one and only instance of the <code>OverworldView</code> class. */
	private static OverworldView	instance;
	/**
	 * flag set on the {@link OverworldView} indicating action menu is
	 * available.
	 */
	public static final int			OWV_ALLOW_ACTION_MENU	= 1 << 1;
	/**
	 * flag set on the {@link OverworldView} indicating evening menu is
	 * available.
	 */
	public static final int			OWV_ALLOW_EVENING_MENU	= 1 << 3;
	/**
	 * flag set on the {@link OverworldView} indicating evening menu is
	 * visible.
	 */
	public static final int			OWV_SHOW_EVENING_MENU	= 1 << 4;
	/** flag indicating the party should be rendered on the map. */
	public static final int			OWV_SHOW_PARTY			= 1 << 0;
	/** 
	 * flag set on the {@link OverworldView} indicating action menu is 
	 * visible. 
	 */
	public static final int OWV_SHOW_ACTION_MENU = 1 << 2;
	/**
	 * Gives access to the singleton instance of {@link OverworldView}.
	 * @return {@link OverworldView}
	 */
	public static OverworldView getInstance() {
		if (OverworldView.instance == null) {
			OverworldView.instance = new OverworldView();
		}
		return OverworldView.instance;
	}
	/** the flags. */
	private long			flags	= 0;
	/** the map widget. */
	private OverworldMap	map;
	/** the view's main container. */
	private Panel			panel;
	/** flag indicating the initialization has been run. */
	private boolean			runInit	= false;
	/**
	 * Sets the map mode.
	 * @param mode the mode
	 */
	public void setMapMode(final int mode) {
		map.setMode(mode);		
	}
	/**
	 * Assigns a flag.
	 * @param flag the flag
	 */
	public void assignFlag(final long flag) {
		flags |= flag;
	}
	/** Centers the world map on the party. */
	public void centerMapOnParty() {
		if (map != null) {
			map.centerMapOnHex(BPParty.getInstance().getCurrentHex());
		}
	}
	/**
	 * Sets possible travel moves, displaying highlights over the selected 
	 * hexes.
	 * @param vertices the list of vertices
	 */
	public void setMoveRadius(final Integer... vertices) {
		map.setMoveRadius(vertices);
	}
	/**
	 * Sets possible travel moves, displaying highlights over the selected 
	 * hexes.
	 * @param vertices the list of vertices
	 */
	public void setPossibleTravelMoves(final Integer... vertices) {
		map.setPossibleTravelMoves(vertices);
	}
	/** Clears all flags that were assigned. */
	public void clearFlags() {
		flags = 0;
	}
	/**
	 * Gets the map's on-screen position.
	 * @return {@link Vector3}
	 */
	public Vector3 getMapPosition() {
		return map.getPosition();
	}
	/**
	 * Gets the map's size.
	 * @return {@link Dimension}
	 */
	public Dimension getMapSize() {
		return map.getPreferredSize();
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void handleKeyEvent(final KeyEvent e) {
		switch (e.getKeyCode()) {
		case KeyEvent.VK_ESCAPE:
			System.out.println("esc");
			GameApplet.getInstance().exit();
			break;
		case KeyEvent.VK_UP:
			// menu.highlightPrevious();
			break;
		case KeyEvent.VK_DOWN:
			// menu.highlightNext();
			break;
		case KeyEvent.VK_ENTER:
			/*
			 * if (menu != null && menu.isVisible() && menu.getHighlighted() !=
			 * null) { menu.getHighlighted().onSelect(); } else if (scroller !=
			 * null && scroller.isVisible() && scroller.isScrolling()) {
			 * scroller.moveTextToTop(); } else if (menuIntro != null &&
			 * menuIntro.isVisible() && menuIntro.getHighlighted() != null) {
			 * menuIntro.getHighlighted().onSelect(); }
			 */
			break;
		case KeyEvent.VK_TAB:
			/*
			 * if (menu != null) { if (e.isShiftDown()) {
			 * menu.highlightPrevious(); } else { menu.highlightNext(); } }
			 */
			break;
		case KeyEvent.VK_BACK_SPACE:
			break;
		case KeyEvent.VK_SPACE:
			break;
		default:
			break;
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void handleMouseOver(final float x, final float y) {
		if (panel != null) {
			panel.handleMouseOver(x, y);
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void handleMousePress(final MouseEvent e, final float x,
			final float y) {
		panel.handleMouseClick(e, x, y);
	}
	/**
	 * Determines if the {@link OverworldView} has a specific flag set.
	 * @param flag the flag
	 * @return true if the flag was set; false otherwise
	 */
	public boolean hasFlag(final long flag) {
		return (flags & flag) == flag;
	}
	/**
	 * Initializes the {@link View}.
	 * @throws Exception if an error occurs
	 */
	private void init() throws Exception {
		panel = new LandscapePagePanel(Panel.LANDSCAPE_TOP);
		map = new OverworldMap(BPConsts.OVERWORLDMAP_WIDTH,
				BPConsts.OVERWORLDMAP_HEIGHT);
		panel.addChild(map);
		panel.addChild(PartyViewer.getInstance());
		panel.setPosition(0, 0, 0);
		/*
		panel.addChild(PartyStatsBar.getInstance());
		PartyStatsBar.getInstance().setPosition(
				map.getPreferredSize().getWidth() - 30, 
				4, 
				1
		);
		*/
		Interface.getInstance().removeViewFlag(
				GlobalConsts.VW_03_CONTROLS_BLOCKED);
		runInit = true;
	}
	/**
	 * Loads the game map.
	 * @param tileDoc the tile map document
	 * @param hexDoc the hex map document
	 */
	public void loadMap(final String tileDoc, final String hexDoc) {
		try {
			if (!runInit) {
				init();
			}
			map.loadMap(Init.getInstance().loadTileMap(tileDoc));
			Init.getInstance().loadHexMap(hexDoc);
		} catch (Exception ex) {
			JOGLErrorHandler.getInstance().fatalError(ex);
		}
	}
	/**
	 * {@inheritDoc}
	 */
	@Override
	public void prepareForRendering() throws Exception {
		if (!runInit) {
			try {
				init();
			} catch (Exception ex) {
				JOGLErrorHandler.getInstance().fatalError(ex);
			}
		}
		panel.prepareForRendering();
		if (hasFlag(OverworldView.OWV_SHOW_PARTY)) {
			// Render.getInstance().registerEntity(partySprite.getSprite());
		}
	}
	/**
	 * Removes a flag.
	 * @param flag the flag
	 */
	public void removeFlag(final long flag) {
		flags &= ~flag;
	}
}
